package com.example.sbbsec.domain.pay.impl;

import com.example.sbbsec.ConvertUtil;
import com.example.sbbsec.WxPayConfig;
import com.example.sbbsec.domain.pay.WxPayNotifyService;
import com.example.sbbsec.domain.pay.entity.WxPayNotify;
import com.example.sbbsec.domain.pay.entity.WxPayOrder;
import com.example.sbbsec.domain.pay.repository.WxPayOrderRepository;
import com.google.common.base.Objects;

import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Map;

import static com.example.sbbsec.WxSignUtil.createSign;
import static com.google.common.base.Strings.isNullOrEmpty;
import static org.slf4j.LoggerFactory.getLogger;

/**
 * Created by Arat.Wu on 2018/10/12.
 */
@Service
@Transactional
public class WxPayNotifyServiceImpl implements WxPayNotifyService {
    private static final Logger LOGGER = getLogger(WxPayNotifyServiceImpl.class);
    @Autowired
    private WxPayConfig wxPayConfig;

    @Override
    public void handleWxPayNotify(WxPayNotify wxPayNotify) {
        LOGGER.info("微信支付回调处理开始,商户订单号:{}", wxPayNotify.getOutTradeNo());

        //回推报文验证
        checkWxPayNotify(wxPayNotify);
        //订单金额验证并更新数据
        checkOrderAndUpdateExam(wxPayNotify);

        LOGGER.info("微信支付回调处理结束,商户订单号:{}", wxPayNotify.getOutTradeNo());
    }

    @Override
    public void updateResBody(Map objectMap) {
        LOGGER.info("微信支付回调,保存回调报文,商户订单号:{}", objectMap.get("orderNo"));
        //wxPayOrderRepository.update(STMT_UPDATE_WX_PAY_ORDER_RES_BODY,objectMap);
        LOGGER.info("微信支付回调,保存回调报文结束,商户订单号:{}", objectMap.get("orderNo"));

    }

    @Override
    public void updateWxPayOrderStatusSecond(String orderNo) {
        //wxPayOrderRepository.update(STMT_UPDATE_WX_PAY_ORDER_STATUS_SECOND, orderNo);
    }

    /**
     * 校验支付回推结果
     *
     * @param wxPayNotify 回推实体
     */
    private void checkWxPayNotify(WxPayNotify wxPayNotify) {
        LOGGER.info("微信支付回调,开始验证回调数据,商户订单号:{}", wxPayNotify.getOutTradeNo());

        //校验return_code
        if (!Objects.equal(wxPayNotify.getReturnCode(), "SUCCESS")) {
            LOGGER.error("微信支付回调异常,订单号:{},异常信息:{}", wxPayNotify.getOutTradeNo(), wxPayNotify.getReturnMsg());
            throw new RuntimeException(wxPayNotify.getReturnMsg());
        }
        //result_code
        if (!Objects.equal(wxPayNotify.getResultCode(), "SUCCESS")) {
            LOGGER.error("微信支付回调异常,订单号:{},错误信息:{}", wxPayNotify.getOutTradeNo(), wxPayNotify.getErrCodeDes());
            throw new RuntimeException(wxPayNotify.getReturnMsg());
        }
        //签名验证
        if (isNullOrEmpty(wxPayNotify.getSign())) {
            LOGGER.error("微信支付回调异常,订单号:{},签名为空", wxPayNotify.getOutTradeNo());
            throw new RuntimeException("签名为空");
        }
        //移除微信计算的签名
        Map<String, Object> stringMap = ConvertUtil.objToMap(wxPayNotify);
        stringMap.remove("sign");
        //重算签名,对比微信给的签名
        if (!Objects.equal(wxPayNotify.getSign(), createSign(stringMap, wxPayConfig.getWxPayKey()))) {
            LOGGER.error("微信支付回调异常,订单号:{},签名不匹配", wxPayNotify.getOutTradeNo());
            throw new RuntimeException("签名不匹配");
        }

        LOGGER.info("微信支付回调,回调数据验证成功,商户订单号:{}", wxPayNotify.getOutTradeNo());
    }


    /**
     * 校验支付回推结果并更新考试支付信息
     *
     * @param wxPayNotify 回推实体
     */
    private void checkOrderAndUpdateExam(WxPayNotify wxPayNotify) {
        LOGGER.info("微信支付回调,开始更新本地数据,商户订单号:{}", wxPayNotify.getOutTradeNo());
        final String orderNo = wxPayNotify.getOutTradeNo();
        //根据订单编号查询系统订单
        final WxPayOrder wxPayOrder = null;//wxPayOrderRepository.get(STMT_GET_WX_PAY_ORDER,orderNo);

        if (wxPayOrder == null) {
            LOGGER.error("微信支付回调异常,订单号:{},查询不到未支付订单,订单可能已支付", wxPayNotify.getOutTradeNo());
            //直接返回微信
            return;
        }
        //比较订单金额
        if (!wxPayOrder.getOrderAmount().equals(wxPayNotify.getTotalFee())) {
            LOGGER.error("微信支付回调异常,订单号:{},支付金额不匹配,本地金额:{},微信返回:{}", wxPayNotify.getOutTradeNo(), wxPayOrder.getOrderAmount(), wxPayNotify.getTotalFee());
            throw new RuntimeException("支付金额不匹配");
        }

        //根据订单号更新订单状态为已支付
//        if(wxPayOrderRepository.update(STMT_UPDATE_WX_PAY_ORDER_STATUS,orderNo)<1){
//            throw new RuntimeException("更新微信订单失败,订单号:" + wxPayNotify.getOutTradeNo());
//        }

        //更新支付状态为支付成功
        //此处代码沿用易宝更新支付考试代码(处理了与微信无关的系统业务,可能会导致更新失败,该情况需要查看原始报文数据 t_wx_pay_order res_body)
        //examRepository.updatePaymentStatusWx(wxPayOrder.getExamId(), wxPayOrder.getPayOrder(), wxPayOrder.getOrderNo(), wxPayOrder.getCheckingType());
        LOGGER.info("微信支付回调,更新本地数据成功,商户订单号:{}", wxPayNotify.getOutTradeNo());
    }

}
